前一天解述了路由的組成,今天來談談端點Endpoint
Endpoint可以視為由RequestDelegate
(middleware那個)跟Metadata集合所組成的類型
Endpoint.cs
public class Endpoint
{
public Endpoint(
RequestDelegate? requestDelegate,
EndpointMetadataCollection? metadata,
string? displayName)
{
// All are allowed to be null
RequestDelegate = requestDelegate;
Metadata = metadata ?? EndpointMetadataCollection.Empty;
DisplayName = displayName;
}
public string? DisplayName { get; }
public EndpointMetadataCollection Metadata { get; }
public RequestDelegate? RequestDelegate { get; }
}
EndpointMetadataCollection
本質上是一個IReadOnlyList<object>
也就是說,任何物件都可以被視為端點的MetaData
包含CorsMetadata, AuthorizeData等等
做為一個Routing 中的Endpoint
最後會用物件RouteEndpoint
來表示RouteEndpoint.cs
public sealed class RouteEndpoint : Endpoint
{
public RouteEndpoint(
RequestDelegate requestDelegate,
RoutePattern routePattern,
int order,
EndpointMetadataCollection? metadata,
string? displayName)
: base(requestDelegate, metadata, displayName)
{
if (requestDelegate == null)
{
throw new ArgumentNullException(nameof(requestDelegate));
}
if (routePattern == null)
{
throw new ArgumentNullException(nameof(routePattern));
}
RoutePattern = routePattern;
Order = order;
}
public int Order { get; }
public RoutePattern RoutePattern { get; }
}
RoutePattern
表示會走到此端點的路由模式
在web應用程式啟動的時候,會建立一個由RouteEndpoint所組成的端點表
最終endpoint的選擇主要會透過兩個Middleware就決定
這個Middleware主要負責的是
Matcher
物件解析路由參數,並加到當前HttpContext
的RouteValues
中HttpContext
最符合的Endpoint,這個endpoint會以Feature的方式存在HttpContext中Matcher
物件頗複雜,預設是DfaMatcher
可以見source code
這個Middleware 主要是透過昨天提到的 app.UseRouting()
所添加到pipeline的
他的工作很簡單,就是執行被加到HttpContext中的Endpoint
主要透過app.UseEndpoints
來添加此Middleware
可以看一下他的source code
稍微節錄一下invoke方法
try
{
var endpoint = httpContext.GetEndpoint();
var requestTask = endpoint.RequestDelegate(httpContext);
}
可以看見他去執行了對應的endpoint的方法
比較常見的是app.MapControllers()
他會去掃你的Controller的 Route Attr. 跟 HttpAttr.作為
endpoint的Metadata的一部份
另外也可以透過MapMethods的方式或是Map[HttpMethod] 的方式註冊endpoint
MapMethods
app.MapMethods("/test",
new[] { HttpMethod.Get.ToString() },
async context => await context.Response.WriteAsync("test"));
MapGet
app.MapGet("/books/{isbn}",
(string isbn) =>
{
return isbn switch
{
"1234567890" => Results.Ok(new Book("1234567890", "The Hitchhiker's Guide to the Galaxy")),
"0987654321" => Results.Ok(new Book("0987654321", "The Restaurant at the End of the Universe")),
_ => Results.NotFound()
};
});